using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Sirenix.OdinInspector;
using UnityEditor;
using UnityEngine;
using UnityEngine.Animations.Rigging;
using static VRig;
#if UNITY_EDITOR

//目前写的是人形泛用, 而且四肢的Construction其实调整权重更大
//对于Pokemon来说其实直接加一个头部的binding + target就行了
public class VRig_LLMBindModule : MonoBehaviour
{
    public VRig extensionRig => GetComponent<VRig>();
    public Rig rigOnGroup;
    [LabelText("动画根骨骼")] public Transform rootNode_Hips;
    public Dictionary<string, string> encoding = new();
    [HideInInspector] public List<Transform> collectedTransform = new();
    [HideInInspector] public List<string> chains = new();
    public string GenParentwithEncoding(Transform curNode, Transform top)
    {
        if (curNode == top) return Getid(curNode);
        Transform curp = curNode.parent;
        string dependChain = Getid(curNode);
        while (curp != top && curp != null)
        {
            dependChain = Getid(curp) + "/" + dependChain;
            curp = curp.parent;
        }
        return dependChain;
        string Getid(Transform t) => encoding[t.name];
    }
    #region  OdinProperty
    [HideInInspector] public int Odin_BindValidFlag = 0;
    private string Odin_DisplayString_GenBindingPrompt => Odin_BindValidFlag switch
    {
        -2 => "生成失败! 请检查骨骼相关命名规范",
        -1 => "您还没有选中根骨骼,绑定后重试!",
        0 => "填入动画根骨骼后->生成绑定提示词",
        1 => "生成成功! 请手动微调",
        2 => "生成中...",
        _ => ""
    };
    private Color Odin_DisplayColor_GenBindingPrompt => Odin_BindValidFlag switch
    {
        -2 => Color.yellow,
        -1 => Color.red,
        0 => Color.white,
        1 => Color.green,
        2 => Color.cyan,
        _ => Color.yellow
    };
    #endregion

    [Button("@Odin_DisplayString_GenBindingPrompt"), GUIColor("@Odin_DisplayColor_GenBindingPrompt")]
    public void GenBindingPrompt()
    {
        collectedTransform.Clear();

        if (rootNode_Hips == null)
        {
            Odin_BindValidFlag = -1;
            throw new System.Exception("您还没有选中根骨骼");
        }

        rescCollect(rootNode_Hips);
        Odin_BindValidFlag = 2;

        ApplyLLMResponse();
        void rescCollect(Transform curNode)
        {
            collectedTransform.Add(curNode);
            if (curNode.childCount != 0)
            {
                for (int i = 0; i < curNode.childCount; i++)
                {
                    rescCollect(curNode.GetChild(i));
                }
            }
        }
    }

    [Button("应用并删除LLM组件")]
    public void ApplyandRemove()
    {
        extensionRig.llmRigEnable = false;
        extensionRig.binded = true;
        extensionRig.SetIKData(rigOnGroup,boneBindUnits);
        this.gameObject.RemoveComponent<VRig_LLMBindModule>();
    }

    [LabelText("生成姿态节点")]
    public VAvatarMaskID selectedGenPose = VAvatarMaskID.FullBody;
    public List<RigIKUnit> boneBindUnits = new();
    public async void ApplyLLMResponse()
    {
        boneBindUnits = ConvertToBoneBindUnits(selectedGenPose);
        var IPHandler = new LLMIP_GenBoneBindingHelper(collectedTransform, chains, boneBindUnits);
        var response = await IPHandler.Generate();
        try
        {
            var result = JsonConvert.DeserializeObject<List<RigIKUnit>>(response);
            GenBoneByLLMResponse(result);
            Odin_BindValidFlag = 1;
            print("结果是:" + result.ToLLMString());
        }
        catch
        {
            Odin_BindValidFlag = -2;
            throw new Exception($"解析失败,请检查响应格式是否正确,可以重试数次or修改Prompt权重:{response}");
        }


    }
    public class LLMIP_GenBoneBindingHelper : LLMInteractPairsBase
    {
        public override string prompt => data;
        private string data;

        public LLMIP_GenBoneBindingHelper(List<Transform> collectedTransform, List<string> chains, List<RigIKUnit> boneBinds)
        {
            string p = "";
            string transforms = string.Join(",", collectedTransform.Select(x => x.name));
            string c = string.Join(",", chains);
            p += "你是一位Unity的骨骼绑定专家，熟悉IK关系和层级以及绑定流程,下面需要你根据人物的骨骼节点，将Transform绑定到特定位置,JsonFormat，严格按照Json格式。只返回绑定结果而不加任何前后缀";
            p += "需要绑定的部位:" + JsonConvert.SerializeObject(boneBinds);
            p += $"Transforms:{{ {transforms} }},";
            data = p;
            jsonManual = true;
        }
    }
    public Transform NameTo(string name) => collectedTransform.Find(x => x.name == name);
    public void GenBoneByLLMResponse(List<RigIKUnit> boneBindUnits)
    {
        //头需要额外处理
        Transform RigGroup = transform.UniqueChild("RigGroup");
        rigOnGroup = RigGroup.gameObject.UniqueComponent<Rig>();

        foreach (var item in boneBindUnits)
        {
            if (item.name == "Head")
            {

            }
            else
            {
                var root = RigGroup.UniqueChild("Rig_" + item.name);
                item.rootTransform = NameTo(item.root);
                item.midTransform = NameTo(item.mid);
                item.tipTransform = NameTo(item.tip);

                item.goal = root.UniqueChild($"Rig_{item.name}_goal");
                item.hint = root.UniqueChild($"Rig_{item.name}_hint");

                item.goal.position = item.tipTransform.position;
                item.hint.position = item.midTransform.position;

                var rigConstraint = root.gameObject.UniqueComponent<TwoBoneIKConstraint>();
                rigConstraint.data.root = item.rootTransform;
                rigConstraint.data.mid = item.midTransform;
                rigConstraint.data.tip = item.tipTransform;
                rigConstraint.data.target = item.goal;
                rigConstraint.data.hint = item.hint;
                item.bodyConstraint = rigConstraint;
            }
        }
        this.boneBindUnits = boneBindUnits;

    }
    public void CollectJsonEnumProperty(string rawJson)
    {
        //var je = new JsonEnumator(rawJson);
        //while (je.ReadNext<string>(out var str))
        //{
        //    print(str);
        //}
    }
}
#endif